diff options
25 files changed, 699 insertions, 282 deletions
diff --git a/chrome/common/plugin_messages.h b/chrome/common/plugin_messages.h index 7b5ce73..111a7db 100644 --- a/chrome/common/plugin_messages.h +++ b/chrome/common/plugin_messages.h @@ -17,8 +17,10 @@ #include "base/gfx/rect.h" #include "base/basictypes.h" #include "chrome/common/ipc_message_utils.h" +#include "chrome/common/webkit_param_traits.h" #include "googleurl/src/gurl.h" #include "third_party/npapi/bindings/npapi.h" +#include "webkit/api/public/WebInputEvent.h" #include "webkit/glue/npruntime_util.h" // Name prefix of the event handle when a message box is displayed. @@ -263,91 +265,43 @@ struct ParamTraits<PluginMsg_DidReceiveResponseParams> { } }; +typedef const WebKit::WebInputEvent* WebInputEventPointer; template <> -struct ParamTraits<NPEvent> { - typedef NPEvent param_type; +struct ParamTraits<WebInputEventPointer> { + typedef WebInputEventPointer param_type; static void Write(Message* m, const param_type& p) { - m->WriteData(reinterpret_cast<const char*>(&p), sizeof(NPEvent)); + m->WriteData(reinterpret_cast<const char*>(p), p->size); } + // Note: upon read, the event has the lifetime of the message. static bool Read(const Message* m, void** iter, param_type* r) { - const char *data; - int data_size = 0; - bool result = m->ReadData(iter, &data, &data_size); - if (!result || data_size != sizeof(NPEvent)) { + const char* data; + int data_length; + if (!m->ReadData(iter, &data, &data_length)) { NOTREACHED(); return false; } - - memcpy(r, data, sizeof(NPEvent)); + if (data_length < static_cast<int>(sizeof(WebKit::WebInputEvent))) { + NOTREACHED(); + return false; + } + param_type event = reinterpret_cast<param_type>(data); + // Check that the data size matches that of the event (we check the latter + // in the delegate). + if (data_length != static_cast<int>(event->size)) { + NOTREACHED(); + return false; + } + *r = event; return true; } static void Log(const param_type& p, std::wstring* l) { -#if defined(OS_WIN) - std::wstring event, wparam, lparam; - lparam = StringPrintf(L"(%d, %d)", LOWORD(p.lParam), HIWORD(p.lParam)); - switch(p.event) { - case WM_KEYDOWN: - event = L"WM_KEYDOWN"; - wparam = StringPrintf(L"%d", p.wParam); - lparam = StringPrintf(L"%d", p.lParam); - break; - case WM_KEYUP: - event = L"WM_KEYDOWN"; - wparam = StringPrintf(L"%d", p.wParam); - lparam = StringPrintf(L"%x", p.lParam); - break; - case WM_MOUSEMOVE: - event = L"WM_MOUSEMOVE"; - if (p.wParam & MK_LBUTTON) { - wparam = L"MK_LBUTTON"; - } else if (p.wParam & MK_MBUTTON) { - wparam = L"MK_MBUTTON"; - } else if (p.wParam & MK_RBUTTON) { - wparam = L"MK_RBUTTON"; - } - break; - case WM_LBUTTONDOWN: - event = L"WM_LBUTTONDOWN"; - break; - case WM_MBUTTONDOWN: - event = L"WM_MBUTTONDOWN"; - break; - case WM_RBUTTONDOWN: - event = L"WM_RBUTTONDOWN"; - break; - case WM_LBUTTONUP: - event = L"WM_LBUTTONUP"; - break; - case WM_MBUTTONUP: - event = L"WM_MBUTTONUP"; - break; - case WM_RBUTTONUP: - event = L"WM_RBUTTONUP"; - break; - } - - if (p.wParam & MK_CONTROL) { - if (!wparam.empty()) - wparam += L" "; - wparam += L"MK_CONTROL"; - } - - if (p.wParam & MK_SHIFT) { - if (!wparam.empty()) - wparam += L" "; - wparam += L"MK_SHIFT"; - } - l->append(L"("); - LogParam(event, l); + LogParam(p->size, l); l->append(L", "); - LogParam(wparam, l); + LogParam(p->type, l); l->append(L", "); - LogParam(lparam, l); + LogParam(p->timeStampSeconds, l); l->append(L")"); -#else - l->append(L"<NPEvent>"); -#endif } }; diff --git a/chrome/common/plugin_messages_internal.h b/chrome/common/plugin_messages_internal.h index ed2e219..20a21f6 100644 --- a/chrome/common/plugin_messages_internal.h +++ b/chrome/common/plugin_messages_internal.h @@ -148,8 +148,8 @@ IPC_BEGIN_MESSAGES(Plugin) IPC_SYNC_MESSAGE_ROUTED0_0(PluginMsg_SetFocus) - IPC_SYNC_MESSAGE_ROUTED1_2(PluginMsg_HandleEvent, - NPEvent /* event */, + IPC_SYNC_MESSAGE_ROUTED1_2(PluginMsg_HandleInputEvent, + IPC::WebInputEventPointer /* event */, bool /* handled */, WebCursor /* cursor type*/) diff --git a/chrome/common/webkit_param_traits.h b/chrome/common/webkit_param_traits.h index bf2630f6..733694a 100644 --- a/chrome/common/webkit_param_traits.h +++ b/chrome/common/webkit_param_traits.h @@ -165,6 +165,9 @@ struct ParamTraits<WebKit::WebInputEvent::Type> { case WebKit::WebInputEvent::MouseLeave: type = L"MouseLeave"; break; + case WebKit::WebInputEvent::MouseEnter: + type = L"MouseEnter"; + break; case WebKit::WebInputEvent::MouseWheel: type = L"MouseWheel"; break; diff --git a/chrome/plugin/webplugin_delegate_stub.cc b/chrome/plugin/webplugin_delegate_stub.cc index b76fc14..2188627 100644 --- a/chrome/plugin/webplugin_delegate_stub.cc +++ b/chrome/plugin/webplugin_delegate_stub.cc @@ -82,7 +82,7 @@ void WebPluginDelegateStub::OnMessageReceived(const IPC::Message& msg) { IPC_MESSAGE_HANDLER(PluginMsg_DidFinishLoadWithReason, OnDidFinishLoadWithReason) IPC_MESSAGE_HANDLER(PluginMsg_SetFocus, OnSetFocus) - IPC_MESSAGE_HANDLER(PluginMsg_HandleEvent, OnHandleEvent) + IPC_MESSAGE_HANDLER(PluginMsg_HandleInputEvent, OnHandleInputEvent) IPC_MESSAGE_HANDLER(PluginMsg_Paint, OnPaint) IPC_MESSAGE_HANDLER(PluginMsg_DidPaint, OnDidPaint) IPC_MESSAGE_HANDLER(PluginMsg_Print, OnPrint) @@ -212,10 +212,11 @@ void WebPluginDelegateStub::OnSetFocus() { delegate_->SetFocus(); } -void WebPluginDelegateStub::OnHandleEvent(const NPEvent& event, - bool* handled, - WebCursor* cursor) { - *handled = delegate_->HandleEvent(const_cast<NPEvent*>(&event), cursor); +void WebPluginDelegateStub::OnHandleInputEvent( + const WebKit::WebInputEvent *event, + bool* handled, + WebCursor* cursor) { + *handled = delegate_->HandleInputEvent(*event, cursor); } void WebPluginDelegateStub::OnPaint(const gfx::Rect& damaged_rect) { diff --git a/chrome/plugin/webplugin_delegate_stub.h b/chrome/plugin/webplugin_delegate_stub.h index d2103a0..b09038c 100644 --- a/chrome/plugin/webplugin_delegate_stub.h +++ b/chrome/plugin/webplugin_delegate_stub.h @@ -24,6 +24,10 @@ struct PluginMsg_DidReceiveResponseParams; struct PluginMsg_URLRequestReply_Params; class WebCursor; +namespace WebKit { +class WebInputEvent; +} + // Converts the IPC messages from WebPluginDelegateProxy into calls to the // actual WebPluginDelegate object. class WebPluginDelegateStub : public IPC::Channel::Listener, @@ -57,8 +61,8 @@ class WebPluginDelegateStub : public IPC::Channel::Listener, void OnDidFinishLoadWithReason(int reason); void OnSetFocus(); - void OnHandleEvent(const NPEvent& event, bool* handled, - WebCursor* cursor); + void OnHandleInputEvent(const WebKit::WebInputEvent* event, + bool* handled, WebCursor* cursor); void OnPaint(const gfx::Rect& damaged_rect); void OnDidPaint(); diff --git a/chrome/renderer/webplugin_delegate_proxy.cc b/chrome/renderer/webplugin_delegate_proxy.cc index 24a8ee4..27f5422 100644 --- a/chrome/renderer/webplugin_delegate_proxy.cc +++ b/chrome/renderer/webplugin_delegate_proxy.cc @@ -610,15 +610,16 @@ void WebPluginDelegateProxy::SetFocus() { Send(new PluginMsg_SetFocus(instance_id_)); } -bool WebPluginDelegateProxy::HandleEvent(NPEvent* event, WebCursor* cursor) { +bool WebPluginDelegateProxy::HandleInputEvent( + const WebKit::WebInputEvent& event, + WebCursor* cursor) { bool handled; // A windowless plugin can enter a modal loop in the context of a // NPP_HandleEvent call, in which case we need to pump messages to // the plugin. We pass of the corresponding event handle to the // plugin process, which is set if the plugin does enter a modal loop. - IPC::SyncMessage* message = new PluginMsg_HandleEvent(instance_id_, - *event, &handled, - cursor); + IPC::SyncMessage* message = new PluginMsg_HandleInputEvent( + instance_id_, &event, &handled, cursor); message->set_pump_messages_event(modal_loop_pump_messages_event_.get()); Send(message); return handled; diff --git a/chrome/renderer/webplugin_delegate_proxy.h b/chrome/renderer/webplugin_delegate_proxy.h index 99bd1e1..be7d6d7 100644 --- a/chrome/renderer/webplugin_delegate_proxy.h +++ b/chrome/renderer/webplugin_delegate_proxy.h @@ -59,7 +59,8 @@ class WebPluginDelegateProxy : public WebPluginDelegate, virtual NPObject* GetPluginScriptableObject(); virtual void DidFinishLoadWithReason(NPReason reason); virtual void SetFocus(); - virtual bool HandleEvent(NPEvent* event, WebCursor* cursor); + virtual bool HandleInputEvent(const WebKit::WebInputEvent& event, + WebCursor* cursor); virtual int GetProcessId(); // IPC::Channel::Listener implementation: diff --git a/third_party/npapi/bindings/npapi.h b/third_party/npapi/bindings/npapi.h index 1035aa3..e60ef7a 100644 --- a/third_party/npapi/bindings/npapi.h +++ b/third_party/npapi/bindings/npapi.h @@ -107,6 +107,7 @@ // On Linux and Mac, be sure to set Mozilla-specific macros. #if defined(OS_LINUX) #define XP_UNIX 1 +#define MOZ_X11 1 #elif defined(OS_MACOSX) #ifndef XP_MACOSX #define XP_MACOSX 1 @@ -133,10 +134,16 @@ #if defined(XP_UNIX) # include <stdio.h> +// BEGIN GOOGLE MODIFICATIONS +#if 0 +// END GOOGLE MODIFICATIONS # if defined(MOZ_X11) # include <X11/Xlib.h> # include <X11/Xutil.h> # endif +// BEGIN GOOGLE MODIFICATIONS +#endif +// END GOOGLE MODIFICATIONS #endif /*----------------------------------------------------------------------*/ @@ -341,16 +348,9 @@ typedef struct int32 type; } NPAnyCallbackStruct; -typedef struct -{ - int32 type; -#ifdef MOZ_X11 - Display* display; - Visual* visual; - Colormap colormap; - unsigned int depth; -#endif -} NPSetWindowCallbackStruct; +// BEGIN GOOGLE MODIFICATIONS +typedef struct _NPSetWindowCallbackStruct NPSetWindowCallbackStruct; +// END GOOGLE MODIFICATIONS typedef struct { @@ -564,6 +564,9 @@ typedef struct _NPEvent uint32 lParam; } NPEvent; #elif defined (XP_UNIX) && defined(MOZ_X11) +// BEGIN GOOGLE MODIFICATIONS +typedef union _XEvent XEvent; +// END GOOGLE MODIFICATIONS typedef XEvent NPEvent; #else typedef void* NPEvent; @@ -578,6 +581,9 @@ typedef CGPathRef NPCGRegion; #elif defined(XP_WIN) typedef HRGN NPRegion; #elif defined(XP_UNIX) && defined(MOZ_X11) +// BEGIN GOOGLE MODIFICATIONS +typedef struct _XRegion *Region; +// END GOOGLE MODIFICATIONS typedef Region NPRegion; #else typedef void *NPRegion; diff --git a/third_party/npapi/bindings/npapi_x11.h b/third_party/npapi/bindings/npapi_x11.h new file mode 100644 index 0000000..c586419 --- /dev/null +++ b/third_party/npapi/bindings/npapi_x11.h @@ -0,0 +1,62 @@ +/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* ***** BEGIN LICENSE BLOCK ***** + * Version: MPL 1.1/GPL 2.0/LGPL 2.1 + * + * The contents of this file are subject to the Mozilla Public License Version + * 1.1 (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * http://www.mozilla.org/MPL/ + * + * Software distributed under the License is distributed on an "AS IS" basis, + * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License + * for the specific language governing rights and limitations under the + * License. + * + * The Original Code is mozilla.org code. + * + * The Initial Developer of the Original Code is + * Netscape Communications Corporation. + * Portions created by the Initial Developer are Copyright (C) 1998 + * the Initial Developer. All Rights Reserved. + * + * Contributor(s): + * + * Alternatively, the contents of this file may be used under the terms of + * either the GNU General Public License Version 2 or later (the "GPL"), or + * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), + * in which case the provisions of the GPL or the LGPL are applicable instead + * of those above. If you wish to allow use of your version of this file only + * under the terms of either the GPL or the LGPL, and not to allow others to + * use your version of this file under the terms of the MPL, indicate your + * decision by deleting the provisions above and replace them with the notice + * and other provisions required by the GPL or the LGPL. If you do not delete + * the provisions above, a recipient may use your version of this file under + * the terms of any one of the MPL, the GPL or the LGPL. + * + * ***** END LICENSE BLOCK ***** */ + +#ifndef THIRD_PARTY_NPAPI_BINDINGS_NPAPI_X11_H_ +#define THIRD_PARTY_NPAPI_BINDINGS_NPAPI_X11_H_ + +// This file was split off the original npapi.h, to avoid including intrusive X +// headers unless necessary. + +#include "third_party/npapi/bindings/npapi.h" + +#ifdef XP_UNIX +#include <X11/Xlib.h> +#include <X11/Xutil.h> + +typedef struct _NPSetWindowCallbackStruct +{ + int32 type; +#ifdef MOZ_X11 + Display* display; + Visual* visual; + Colormap colormap; + unsigned int depth; +#endif +} NPSetWindowCallbackStruct; +#endif + +#endif // THIRD_PARTY_NPAPI_BINDINGS_NPAPI_X11_H_ diff --git a/webkit/api/public/WebInputEvent.h b/webkit/api/public/WebInputEvent.h index f232ce5..dbb6602 100644 --- a/webkit/api/public/WebInputEvent.h +++ b/webkit/api/public/WebInputEvent.h @@ -49,7 +49,11 @@ namespace WebKit { class WebInputEvent { public: - WebInputEvent() : type(None), modifiers(0) { } + WebInputEvent(unsigned sizeParam = sizeof(WebInputEvent)) + : size(sizeParam) + , type(Undefined) + , modifiers(0) + , timeStampSeconds(0.0) { } // There are two schemes used for keyboard input. On Windows (and, // interestingly enough, on Mac Carbon) there are two events for a @@ -65,12 +69,13 @@ namespace WebKit { // indicate this. enum Type { - None = -1, + Undefined = -1, // WebMouseEvent MouseDown, MouseUp, MouseMove, + MouseEnter, MouseLeave, // WebMouseWheelEvent @@ -85,18 +90,25 @@ namespace WebKit { enum Modifiers { // modifiers for all events: - ShiftKey = 1 << 0, - ControlKey = 1 << 1, - AltKey = 1 << 2, - MetaKey = 1 << 3, + ShiftKey = 1 << 0, + ControlKey = 1 << 1, + AltKey = 1 << 2, + MetaKey = 1 << 3, // modifiers for keyboard events: - IsKeyPad = 1 << 4, - IsAutoRepeat = 1 << 5 + IsKeyPad = 1 << 4, + IsAutoRepeat = 1 << 5, + + // modifiers for mouse events: + LeftButtonDown = 1 << 6, + MiddleButtonDown = 1 << 7, + RightButtonDown = 1 << 8, }; + unsigned size; // The size of this structure, for serialization. Type type; int modifiers; + double timeStampSeconds; // Seconds since epoch. // Returns true if the WebInputEvent |type| is a keyboard event. static bool isKeyboardEventType(int type) @@ -151,8 +163,9 @@ namespace WebKit { // easier to leave it always false than ifdef. bool isSystemKey; - WebKeyboardEvent() - : windowsKeyCode(0) + WebKeyboardEvent(unsigned sizeParam = sizeof(WebKeyboardEvent)) + : WebInputEvent(sizeParam) + , windowsKeyCode(0) , nativeKeyCode(0) , isSystemKey(false) { @@ -181,18 +194,21 @@ namespace WebKit { Button button; int x; int y; + int windowX; + int windowY; int globalX; int globalY; - double timeStampSeconds; // Seconds since epoch. int clickCount; - WebMouseEvent() - : button(ButtonNone) + WebMouseEvent(unsigned sizeParam = sizeof(WebMouseEvent)) + : WebInputEvent(sizeParam) + , button(ButtonNone) , x(0) , y(0) + , windowX(0) + , windowY(0) , globalX(0) , globalY(0) - , timeStampSeconds(0.0) , clickCount(0) { } @@ -208,8 +224,9 @@ namespace WebKit { float wheelTicksY; bool scrollByPage; - WebMouseWheelEvent() - : deltaX(0.0f) + WebMouseWheelEvent(unsigned sizeParam = sizeof(WebMouseWheelEvent)) + : WebMouseEvent(sizeParam) + , deltaX(0.0f) , deltaY(0.0f) , wheelTicksX(0.0f) , wheelTicksY(0.0f) diff --git a/webkit/api/src/gtk/WebInputEventFactory.cpp b/webkit/api/src/gtk/WebInputEventFactory.cpp index 17506b2..24a4e4b 100644 --- a/webkit/api/src/gtk/WebInputEventFactory.cpp +++ b/webkit/api/src/gtk/WebInputEventFactory.cpp @@ -62,6 +62,12 @@ static int gdkStateToWebEventModifiers(guint state) if (state & GDK_META_MASK) modifiers |= WebInputEvent::MetaKey; #endif + if (state & GDK_BUTTON1_MASK) + modifiers |= WebInputEvent::LeftButtonDown; + if (state & GDK_BUTTON2_MASK) + modifiers |= WebInputEvent::MiddleButtonDown; + if (state & GDK_BUTTON3_MASK) + modifiers |= WebInputEvent::RightButtonDown; return modifiers; } @@ -71,6 +77,7 @@ WebKeyboardEvent WebInputEventFactory::keyboardEvent(const GdkEventKey* event) { WebKeyboardEvent result; + result.timeStampSeconds = gdkEventTimeToWebEventTime(event->time); result.modifiers = gdkStateToWebEventModifiers(event->state); switch (event->type) { @@ -123,6 +130,8 @@ WebMouseEvent WebInputEventFactory::mouseEvent(const GdkEventButton* event) result.modifiers = gdkStateToWebEventModifiers(event->state); result.x = static_cast<int>(event->x); result.y = static_cast<int>(event->y); + result.windowX = result.x; + result.windowY = result.y; result.globalX = static_cast<int>(event->x_root); result.globalY = static_cast<int>(event->y_root); result.clickCount = 0; @@ -165,6 +174,8 @@ WebMouseEvent WebInputEventFactory::mouseEvent(const GdkEventMotion* event) result.modifiers = gdkStateToWebEventModifiers(event->state); result.x = static_cast<int>(event->x); result.y = static_cast<int>(event->y); + result.windowX = result.x; + result.windowY = result.y; result.globalX = static_cast<int>(event->x_root); result.globalY = static_cast<int>(event->y_root); @@ -200,6 +211,8 @@ WebMouseWheelEvent WebInputEventFactory::mouseWheelEvent(const GdkEventScroll* e result.modifiers = gdkStateToWebEventModifiers(event->state); result.x = static_cast<int>(event->x); result.y = static_cast<int>(event->y); + result.windowX = result.x; + result.windowY = result.y; result.globalX = static_cast<int>(event->x_root); result.globalY = static_cast<int>(event->y_root); diff --git a/webkit/api/src/mac/WebInputEventFactory.mm b/webkit/api/src/mac/WebInputEventFactory.mm index e9a0d59..33378c9 100644 --- a/webkit/api/src/mac/WebInputEventFactory.mm +++ b/webkit/api/src/mac/WebInputEventFactory.mm @@ -836,6 +836,7 @@ static inline int modifiersFromEvent(NSEvent* event) { modifiers |= WebInputEvent::AltKey; if ([event modifierFlags] & NSCommandKeyMask) modifiers |= WebInputEvent::MetaKey; + // TODO(port): Set mouse button states return modifiers; } @@ -899,6 +900,8 @@ WebKeyboardEvent WebInputEventFactory::keyboardEvent(NSEvent* event) maxLength:sizeof(result.keyIdentifier) encoding:NSASCIIStringEncoding]; + result.timeStampSeconds = [event timestamp]; + return result; } @@ -970,6 +973,8 @@ WebMouseEvent WebInputEventFactory::mouseEvent(NSEvent* event, NSView* view) location = [view convertPoint:windowLocal fromView:nil]; result.y = [view frame].size.height - location.y; // flip y result.x = location.x; + result.windowX = result.x; + result.windowY = result.y; result.modifiers = modifiersFromEvent(event); @@ -997,6 +1002,8 @@ WebMouseWheelEvent WebInputEventFactory::mouseWheelEvent(NSEvent* event, NSView* location = [view convertPoint:windowLocal fromView:nil]; result.x = location.x; result.y = [view frame].size.height - location.y; // flip y + result.windowX = result.x; + result.windowY = result.y; // Of Mice and Men // --------------- @@ -1125,6 +1132,8 @@ WebMouseWheelEvent WebInputEventFactory::mouseWheelEvent(NSEvent* event, NSView* result.deltaY = [event deltaY] * scrollbarPixelsPerCocoaTick; } + result.timeStampSeconds = [event timestamp]; + return result; } diff --git a/webkit/api/src/win/WebInputEventFactory.cpp b/webkit/api/src/win/WebInputEventFactory.cpp index 0a450d0..afc607b 100644 --- a/webkit/api/src/win/WebInputEventFactory.cpp +++ b/webkit/api/src/win/WebInputEventFactory.cpp @@ -91,6 +91,12 @@ WebKeyboardEvent WebInputEventFactory::keyboardEvent(HWND hwnd, UINT message, { WebKeyboardEvent result; + // TODO(pkasting): http://b/1117926 Are we guaranteed that the message that + // GetMessageTime() refers to is the same one that we're passed in? Perhaps + // one of the construction parameters should be the time passed by the + // caller, who would know for sure. + result.timeStampSeconds = GetMessageTime() / 1000.0; + result.windowsKeyCode = result.nativeKeyCode = static_cast<int>(wparam); switch (message) { @@ -130,6 +136,8 @@ WebKeyboardEvent WebInputEventFactory::keyboardEvent(HWND hwnd, UINT message, result.modifiers |= WebInputEvent::ControlKey; if (GetKeyState(VK_MENU) & 0x8000) result.modifiers |= WebInputEvent::AltKey; + // NOTE: There doesn't seem to be a way to query the mouse button state in + // this case. if (LOWORD(lparam) > 1) result.modifiers |= WebInputEvent::IsAutoRepeat; @@ -222,6 +230,8 @@ WebMouseEvent WebInputEventFactory::mouseEvent(HWND hwnd, UINT message, result.x = static_cast<short>(LOWORD(lparam)); result.y = static_cast<short>(HIWORD(lparam)); + result.windowX = result.x; + result.windowY = result.y; POINT globalPoint = { result.x, result.y }; ClientToScreen(hwnd, &globalPoint); @@ -272,6 +282,12 @@ WebMouseEvent WebInputEventFactory::mouseEvent(HWND hwnd, UINT message, result.modifiers |= WebInputEvent::ShiftKey; if (GetKeyState(VK_MENU) & 0x8000) result.modifiers |= WebInputEvent::AltKey; + if (wparam & MK_LBUTTON) + result.modifiers |= WebInputEvent::LeftButtonDown; + if (wparam & MK_MBUTTON) + result.modifiers |= WebInputEvent::MiddleButtonDown; + if (wparam & MK_RBUTTON) + result.modifiers |= WebInputEvent::RightButtonDown; return result; } @@ -284,6 +300,13 @@ WebMouseWheelEvent WebInputEventFactory::mouseWheelEvent(HWND hwnd, UINT message WebMouseWheelEvent result; //(WebInputEvent::Uninitialized()); result.type = WebInputEvent::MouseWheel; + + // TODO(pkasting): http://b/1117926 Are we guaranteed that the message that + // GetMessageTime() refers to is the same one that we're passed in? Perhaps + // one of the construction parameters should be the time passed by the + // caller, who would know for sure. + result.timeStampSeconds = GetMessageTime() / 1000.0; + result.button = WebMouseEvent::ButtonNone; // Get key state, coordinates, and wheel delta from event. @@ -302,6 +325,8 @@ WebMouseWheelEvent WebInputEventFactory::mouseWheelEvent(HWND hwnd, UINT message keyState |= MK_SHIFT; if (getKeyState(VK_CONTROL)) keyState |= MK_CONTROL; + // NOTE: There doesn't seem to be a way to query the mouse button state + // in this case. POINT cursorPosition = {0}; GetCursorPos(&cursorPosition); @@ -354,12 +379,20 @@ WebMouseWheelEvent WebInputEventFactory::mouseWheelEvent(HWND hwnd, UINT message result.modifiers |= WebInputEvent::ControlKey; if (getKeyState(VK_MENU) & 0x8000) result.modifiers |= WebInputEvent::AltKey; + if (keyState & MK_LBUTTON) + result.modifiers |= WebInputEvent::LeftButtonDown; + if (keyState & MK_MBUTTON) + result.modifiers |= WebInputEvent::MiddleButtonDown; + if (keyState & MK_RBUTTON) + result.modifiers |= WebInputEvent::RightButtonDown; // Set coordinates by translating event coordinates from screen to client. POINT clientPoint = { result.globalX, result.globalY }; MapWindowPoints(NULL, hwnd, &clientPoint, 1); result.x = clientPoint.x; result.y = clientPoint.y; + result.windowX = result.x; + result.windowY = result.y; // Convert wheel delta amount to a number of pixels to scroll. // diff --git a/webkit/glue/event_conversion.cc b/webkit/glue/event_conversion.cc index 2a3bbff..40e9445 100644 --- a/webkit/glue/event_conversion.cc +++ b/webkit/glue/event_conversion.cc @@ -5,7 +5,11 @@ #include "config.h" #include "webkit/glue/event_conversion.h" +#include "EventNames.h" +#include "FrameView.h" #include "KeyboardCodes.h" +#include "KeyboardEvent.h" +#include "MouseEvent.h" #include "StringImpl.h" // This is so that the KJS build works #include "PlatformKeyboardEvent.h" #include "PlatformMouseEvent.h" @@ -149,3 +153,88 @@ bool MakePlatformKeyboardEvent::IsCharacterKey() const { } return true; } + +static int GetWebInputModifiers(const WebCore::UIEventWithKeyState& event) { + int modifiers = 0; + if (event.ctrlKey()) + modifiers |= WebInputEvent::ControlKey; + if (event.shiftKey()) + modifiers |= WebInputEvent::ShiftKey; + if (event.altKey()) + modifiers |= WebInputEvent::AltKey; + if (event.metaKey()) + modifiers |= WebInputEvent::MetaKey; + return modifiers; +} + + +bool ToWebMouseEvent(const WebCore::FrameView& view, + const WebCore::MouseEvent& event, + WebKit::WebMouseEvent* web_event) { + if (event.type() == WebCore::eventNames().mousemoveEvent) { + web_event->type = WebInputEvent::MouseMove; + } else if (event.type() == WebCore::eventNames().mouseoutEvent) { + web_event->type = WebInputEvent::MouseLeave; + } else if (event.type() == WebCore::eventNames().mouseoverEvent) { + web_event->type = WebInputEvent::MouseEnter; + } else if (event.type() == WebCore::eventNames().mousedownEvent) { + web_event->type = WebInputEvent::MouseDown; + } else if (event.type() == WebCore::eventNames().mouseupEvent) { + web_event->type = WebInputEvent::MouseUp; + } else { + // Skip all other mouse events. + return false; + } + web_event->timeStampSeconds = event.timeStamp() * 1.0e-3; + switch (event.button()) { + case WebCore::LeftButton: + web_event->button = WebMouseEvent::ButtonLeft; + break; + case WebCore::MiddleButton: + web_event->button = WebMouseEvent::ButtonMiddle; + break; + case WebCore::RightButton: + web_event->button = WebMouseEvent::ButtonRight; + break; + } + web_event->modifiers = GetWebInputModifiers(event); + if (event.buttonDown()) { + switch (event.button()) { + case WebCore::LeftButton: + web_event->modifiers |= WebInputEvent::LeftButtonDown; + break; + case WebCore::MiddleButton: + web_event->modifiers |= WebInputEvent::MiddleButtonDown; + break; + case WebCore::RightButton: + web_event->modifiers |= WebInputEvent::RightButtonDown; + break; + } + } + WebCore::IntPoint p = view.contentsToWindow(WebCore::IntPoint(event.pageX(), + event.pageY())); + web_event->globalX = event.screenX(); + web_event->globalY = event.screenY(); + web_event->windowX = p.x(); + web_event->windowY = p.y(); + web_event->x = event.offsetX(); + web_event->y = event.offsetY(); + return true; +} + +bool ToWebKeyboardEvent(const WebCore::KeyboardEvent& event, + WebKeyboardEvent* web_event) { + if (event.type() == WebCore::eventNames().keydownEvent) { + web_event->type = WebInputEvent::KeyDown; + } else if (event.type() == WebCore::eventNames().keyupEvent) { + web_event->type = WebInputEvent::KeyUp; + } else { + // Skip all other keyboard events. + return false; + } + web_event->modifiers = GetWebInputModifiers(event); + web_event->timeStampSeconds = event.timeStamp() * 1.0e-3; + web_event->windowsKeyCode = event.keyCode(); + web_event->nativeKeyCode = event.keyEvent()->nativeVirtualKeyCode(); + return true; +} diff --git a/webkit/glue/event_conversion.h b/webkit/glue/event_conversion.h index 5b83c97..ef82cdb 100644 --- a/webkit/glue/event_conversion.h +++ b/webkit/glue/event_conversion.h @@ -15,7 +15,10 @@ MSVC_PUSH_WARNING_LEVEL(0); MSVC_POP_WARNING(); namespace WebCore { - class Widget; +class FrameView; +class KeyboardEvent; +class MouseEvent; +class Widget; } namespace WebKit { @@ -46,4 +49,19 @@ class MakePlatformKeyboardEvent : public WebCore::PlatformKeyboardEvent { bool IsCharacterKey() const; }; +// Converts a WebCore::MouseEvent to a corresponding WebMouseEvent. view is the +// FrameView corresponding to the event. +// Returns true if successful. +// NOTE: This is only implemented for mousemove, mouseover, mouseout, mousedown +// and mouseup. +bool ToWebMouseEvent(const WebCore::FrameView& view, + const WebCore::MouseEvent& event, + WebKit::WebMouseEvent* web_event); + +// Converts a WebCore::KeyboardEvent to a corresponding WebKeyboardEvent. +// Returns true if successful. +// NOTE: This is only implemented for keydown and keyup. +bool ToWebKeyboardEvent(const WebCore::KeyboardEvent& event, + WebKit::WebKeyboardEvent* web_event); + #endif // WEBKIT_GLUE_EVENT_CONVERSION_H_ 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; } diff --git a/webkit/glue/webplugin_delegate.h b/webkit/glue/webplugin_delegate.h index a6e711bd..36f943b 100644 --- a/webkit/glue/webplugin_delegate.h +++ b/webkit/glue/webplugin_delegate.h @@ -21,6 +21,10 @@ class WebCursor; class WebPlugin; class WebPluginResourceClient; +namespace WebKit { +class WebInputEvent; +} + namespace gfx { class Rect; } @@ -87,7 +91,8 @@ class WebPluginDelegate { // For windowless plugins, gives them a user event like mouse/keyboard. // Returns whether the event was handled. - virtual bool HandleEvent(NPEvent* event, WebCursor* cursor) = 0; + virtual bool HandleInputEvent(const WebKit::WebInputEvent& event, + WebCursor* cursor) = 0; // Gets the NPObject associated with the plugin for scripting. virtual NPObject* GetPluginScriptableObject() = 0; diff --git a/webkit/glue/webplugin_impl.cc b/webkit/glue/webplugin_impl.cc index f3511f6..0441000 100644 --- a/webkit/glue/webplugin_impl.cc +++ b/webkit/glue/webplugin_impl.cc @@ -30,7 +30,9 @@ #include "Page.h" #include "PlatformContextSkia.h" #include "PlatformMouseEvent.h" +#include "PlatformKeyboardEvent.h" #include "PlatformString.h" +#include "PlatformWidget.h" #include "RenderBox.h" #include "ResourceHandle.h" #include "ResourceHandleClient.h" @@ -47,11 +49,13 @@ #include "base/string_util.h" #include "base/sys_string_conversions.h" #include "net/base/escape.h" +#include "webkit/api/public/WebInputEvent.h" #include "webkit/api/public/WebKit.h" #include "webkit/api/public/WebKitClient.h" #include "webkit/api/public/WebString.h" #include "webkit/api/public/WebURL.h" #include "webkit/glue/chrome_client_impl.h" +#include "webkit/glue/event_conversion.h" #include "webkit/glue/glue_util.h" #include "webkit/glue/multipart_response_delegate.h" #include "webkit/glue/webcursor.h" @@ -62,6 +66,10 @@ #include "webkit/glue/webview_impl.h" #include "googleurl/src/gurl.h" +using WebKit::WebKeyboardEvent; +using WebKit::WebInputEvent; +using WebKit::WebMouseEvent; + // This class handles individual multipart responses. It is instantiated when // we receive HTTP status code 206 in the HTTP response. This indicates // that the response could have multiple parts each separated by a boundary @@ -768,42 +776,16 @@ void WebPluginImpl::handleEvent(WebCore::Event* event) { } void WebPluginImpl::handleMouseEvent(WebCore::MouseEvent* event) { -#if defined(OS_WIN) DCHECK(parent()->isFrameView()); // We cache the parent FrameView here as the plugin widget could be deleted // in the call to HandleEvent. See http://b/issue?id=1362948 WebCore::FrameView* parent_view = static_cast<WebCore::FrameView*>(parent()); - WebCore::IntPoint p = - parent_view->contentsToWindow(WebCore::IntPoint(event->pageX(), - event->pageY())); - NPEvent np_event; - np_event.lParam = static_cast<uint32>(MAKELPARAM(p.x(), p.y())); - np_event.wParam = 0; - - if (event->ctrlKey()) - np_event.wParam |= MK_CONTROL; - if (event->shiftKey()) - np_event.wParam |= MK_SHIFT; - - if ((event->type() == WebCore::eventNames().mousemoveEvent) || - (event->type() == WebCore::eventNames().mouseoutEvent) || - (event->type() == WebCore::eventNames().mouseoverEvent)) { - np_event.event = WM_MOUSEMOVE; - if (event->buttonDown()) { - switch (event->button()) { - case WebCore::LeftButton: - np_event.wParam |= MK_LBUTTON; - break; - case WebCore::MiddleButton: - np_event.wParam |= MK_MBUTTON; - break; - case WebCore::RightButton: - np_event.wParam |= MK_RBUTTON; - break; - } - } - } else if (event->type() == WebCore::eventNames().mousedownEvent) { + WebMouseEvent web_event; + if (!ToWebMouseEvent(*parent_view, *event, &web_event)) + return; + + if (event->type() == WebCore::eventNames().mousedownEvent) { // Ensure that the frame containing the plugin has focus. WebCore::Frame* containing_frame = webframe_->frame(); if (WebCore::Page* current_page = containing_frame->page()) { @@ -811,46 +793,13 @@ void WebPluginImpl::handleMouseEvent(WebCore::MouseEvent* event) { } // Give focus to our containing HTMLPluginElement. containing_frame->document()->setFocusedNode(element_); - - // Ideally we'd translate to WM_xBUTTONDBLCLK here if the click count were - // a multiple of 2. But there seems to be no way to get at the click count - // or the original Windows message from the WebCore::Event. - switch (event->button()) { - case WebCore::LeftButton: - np_event.event = WM_LBUTTONDOWN; - np_event.wParam |= MK_LBUTTON; - break; - case WebCore::MiddleButton: - np_event.event = WM_MBUTTONDOWN; - np_event.wParam |= MK_MBUTTON; - break; - case WebCore::RightButton: - np_event.event = WM_RBUTTONDOWN; - np_event.wParam |= MK_RBUTTON; - break; - } - } else if (event->type() == WebCore::eventNames().mouseupEvent) { - switch (event->button()) { - case WebCore::LeftButton: - np_event.event = WM_LBUTTONUP; - break; - case WebCore::MiddleButton: - np_event.event = WM_MBUTTONUP; - break; - case WebCore::RightButton: - np_event.event = WM_RBUTTONUP; - break; - } - } else { - // Skip all other mouse events. - return; } // TODO(pkasting): http://b/1119691 This conditional seems exactly backwards, // but it matches Safari's code, and if I reverse it, giving focus to a // transparent (windowless) plugin fails. WebCursor cursor; - if (!delegate_->HandleEvent(&np_event, &cursor)) + if (!delegate_->HandleInputEvent(web_event, &cursor)) event->setDefaultHandled(); WebCore::Page* page = parent_view->frame()->page(); @@ -864,35 +813,16 @@ void WebPluginImpl::handleMouseEvent(WebCore::MouseEvent* event) { // event. We need to reflect the changed cursor in the frame view as the // mouse is moved in the boundaries of the windowless plugin. chrome_client->SetCursorForPlugin(cursor); - -#else - NOTIMPLEMENTED(); -#endif } void WebPluginImpl::handleKeyboardEvent(WebCore::KeyboardEvent* event) { -#if defined(OS_WIN) - NPEvent np_event; - np_event.wParam = event->keyCode(); - - if (event->type() == WebCore::eventNames().keydownEvent) { - np_event.event = WM_KEYDOWN; - np_event.lParam = 0; - } else if (event->type() == WebCore::eventNames().keyupEvent) { - np_event.event = WM_KEYUP; - np_event.lParam = 0x8000; - } else { - // Skip all other keyboard events. + WebKeyboardEvent web_event; + if (!ToWebKeyboardEvent(*event, &web_event)) return; - } - // TODO(pkasting): http://b/1119691 See above. WebCursor current_web_cursor; - if (!delegate_->HandleEvent(&np_event, ¤t_web_cursor)) + if (!delegate_->HandleInputEvent(web_event, ¤t_web_cursor)) event->setDefaultHandled(); -#else - NOTIMPLEMENTED(); -#endif } NPObject* WebPluginImpl::GetPluginScriptableObject() { |